from flask import request
from flask_restx import Resource, Namespace, fields
from flask_jwt_extended import create_access_token, create_refresh_token, jwt_required, get_jwt_identity
from datetime import datetime
import hashlib
import bcrypt

import app1
from app1.models import Zbfwbuser, Zbfwbrole, Zbfwbperm, Zbfwbuserrole, Zbfwbroleperm

# 创建命名空间
auth_rbac_ns = Namespace('auth_rbac', description='Authentication operations with RBAC')

# 定义用户模型
user_model = auth_rbac_ns.model('User', {
    'username': fields.String(required=True, description='Username'),
    'password': fields.String(required=True, description='Password')
})

perms_model = auth_rbac_ns.model('perms', {
    'permissions': fields.List(fields.Integer, description='权限列表', default=[]),
})


def md5_hash(password):
    """使用MD5对密码进行加密"""
    return hashlib.md5(password.encode('utf-8')).hexdigest()


# 登录接口 - 密文密码
@auth_rbac_ns.route('/login_rbac')
class AuthRbacResource(Resource):
    @auth_rbac_ns.expect(user_model)
    def post(self):
        """ 密文密码登录 """
        try:
            data = request.get_json()
            user = Zbfwbuser.query.filter_by(t_zbfwb_user_name=data['username']).first()

            if user and user.t_zbfwb_user_passwd == data['password']:
                # 获取用户角色
                user_roles = Zbfwbuserrole.query.filter_by(uid=user.t_zbfwb_user_id).all()
                roles = [role.rid for role in user_roles]
                # 获取角色权限
                role_permissions = Zbfwbroleperm.query.filter(Zbfwbroleperm.rid.in_(roles)).all()
                permissions = [perm.pid for perm in role_permissions]

                # 生成访问令牌和刷新令牌
                access_token = create_access_token(identity=user.t_zbfwb_user_id,
                                                   additional_claims={'roles': roles, 'permissions': permissions})
                refresh_token = create_refresh_token(identity=user.t_zbfwb_user_id)

                expire_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                return {'access_token': access_token, 'refresh_token': refresh_token, 'expire': expire_time}, 200

            return {'message': 'Invalid credentials'}, 401
        except Exception as e:
            response_data = {
                "message": {
                    "result": 400,  # 查询异常
                    "result_text": f"查询异常: {str(e)}",
                    "count": 0,
                    "data": []
                }
            }
            return response_data, 400


# 登录接口 - 明文密码
@auth_rbac_ns.route('/login_rbac_plain')
class AuthRbacPlainResource(Resource):
    @auth_rbac_ns.expect(user_model)
    def post(self):
        """ 明文密码登录 """
        try:
            data = request.get_json()

            # 对密码进行MD5加密
            hashed_password = md5_hash(data['password'])

            # 查询数据库，查找对应用户名和加密后的密码
            user = Zbfwbuser.query.filter_by(t_zbfwb_user_name=data['username']).first()

            # 检查用户名和密码是否匹配
            if user and user.t_zbfwb_user_passwd == hashed_password:
                # 获取用户角色
                user_roles = Zbfwbuserrole.query.filter_by(uid=user.t_zbfwb_user_id).all()
                roles = [role.rid for role in user_roles]
                # 获取角色权限
                role_permissions = Zbfwbroleperm.query.filter(Zbfwbroleperm.rid.in_(roles)).all()
                permissions = [perm.pid for perm in role_permissions]

                # 生成访问令牌和刷新令牌
                access_token = create_access_token(identity=user.t_zbfwb_user_id,
                                                   additional_claims={'roles': roles, 'permissions': permissions})
                refresh_token = create_refresh_token(identity=user.t_zbfwb_user_id)

                expire_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                return {'access_token': access_token, 'refresh_token': refresh_token, 'expire': expire_time}, 200

            return {'message': 'Invalid credentials'}, 401
        except Exception as e:
            response_data = {
                "message": {
                    "result": 400,  # 查询异常
                    "result_text": f"查询异常: {str(e)}",
                    "count": 0,
                    "data": []
                }
            }
            return response_data, 400


@auth_rbac_ns.route('/login_rbac_bcrypt')
class AuthRbacBcryptResource(Resource):
    @auth_rbac_ns.expect(user_model)
    def post(self):
        """密文密码登录（要求客户端传 bcrypt 加密后的密码）"""
        try:
            data = request.get_json()
            user = Zbfwbuser.query.filter_by(t_zbfwb_user_name=data['username']).first()

            if not user:
                return {'message': 'Invalid credentials'}, 401

            # 客户端必须传 bcrypt 加密后的密码（直接比对）
            if user.t_zbfwb_user_passwd == data['password']:
                # 获取用户角色和权限
                user_roles = Zbfwbuserrole.query.filter_by(uid=user.t_zbfwb_user_id).all()
                roles = [role.rid for role in user_roles]
                role_permissions = Zbfwbroleperm.query.filter(Zbfwbroleperm.rid.in_(roles)).all()
                permissions = [perm.pid for perm in role_permissions]

                # 生成令牌
                access_token = create_access_token(
                    identity=user.t_zbfwb_user_id,
                    additional_claims={'roles': roles, 'permissions': permissions}
                )
                refresh_token = create_refresh_token(identity=user.t_zbfwb_user_id)

                return {
                    'access_token': access_token,
                    'refresh_token': refresh_token,
                    'expire': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                }, 200

            return {'message': 'Invalid credentials'}, 401
        except Exception as e:
            return {
                "message": {
                    "result": 400,
                    "result_text": f"查询异常: {str(e)}",
                    "count": 0,
                    "data": []
                }
            }, 400


# 登录接口 - 明文密码 (使用 bcrypt 加密验证)
@auth_rbac_ns.route('/login_rbac_plain_bcrypt')
class AuthRbacPlainBcryptResource(Resource):
    @auth_rbac_ns.expect(user_model)
    def post(self):
        """ 明文密码登录 (使用 bcrypt 验证) """
        try:
            data = request.get_json()
            username = data['username']
            password = data['password'].encode('utf-8')  # 将用户输入的密码转为 bytes

            # 查询数据库，查找对应用户
            user = Zbfwbuser.query.filter_by(t_zbfwb_user_name=username).first()

            if not user:
                return {'message': 'Invalid credentials'}, 401

            # 获取数据库存储的 bcrypt 哈希密码（需转回 bytes）
            stored_password = user.t_zbfwb_user_passwd.encode('utf-8')

            # 使用 bcrypt.checkpw 验证密码
            if bcrypt.checkpw(password, stored_password):
                # 获取用户角色
                user_roles = Zbfwbuserrole.query.filter_by(uid=user.t_zbfwb_user_id).all()
                roles = [role.rid for role in user_roles]
                # 获取角色权限
                role_permissions = Zbfwbroleperm.query.filter(Zbfwbroleperm.rid.in_(roles)).all()
                permissions = [perm.pid for perm in role_permissions]

                # 生成访问令牌和刷新令牌
                access_token = create_access_token(
                    identity=user.t_zbfwb_user_id,
                    additional_claims={'roles': roles, 'permissions': permissions}
                )
                refresh_token = create_refresh_token(identity=user.t_zbfwb_user_id)

                expire_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                return {
                    'access_token': access_token,
                    'refresh_token': refresh_token,
                    'expire': expire_time
                }, 200

            return {'message': 'Invalid credentials'}, 401
        except Exception as e:
            response_data = {
                "message": {
                    "result": 400,  # 查询异常
                    "result_text": f"查询异常: {str(e)}",
                    "count": 0,
                    "data": []
                }
            }
            return response_data, 400


# 获取用户信息及其角色和权限
@auth_rbac_ns.route('/user-info_rbac')
class ProtectedRbacResource(Resource):
    @jwt_required()
    def post(self):
        """ 获取用户信息及其角色和权限 """
        try:
            current_user = get_jwt_identity()  # 获取当前用户的身份信息

            # 获取当前用户的角色和权限
            user = Zbfwbuser.query.get(current_user)

            if user:
                user_roles = Zbfwbuserrole.query.filter_by(uid=user.t_zbfwb_user_id).all()
                roles = [role.rid for role in user_roles]

                # 获取角色权限
                role_permissions = Zbfwbroleperm.query.filter(Zbfwbroleperm.rid.in_(roles)).all()
                permissions = [perm.pid for perm in role_permissions]

                # 返回用户信息、角色和权限
                user_info = {
                    'username': user.t_zbfwb_user_name,
                    'roles': roles,
                    'permissions': permissions
                }
                return user_info, 200

            return {'message': 'User not found'}, 404
        except Exception as e:
            response_data = {
                "message": {
                    "result": 400,  # 查询异常
                    "result_text": f"查询异常: {str(e)}",
                    "count": 0,
                    "data": []
                }
            }
            return response_data, 400


# 检查当前用户是否有指定权限
@auth_rbac_ns.route('/check-permission')
class CheckPermissionResource(Resource):
    @auth_rbac_ns.expect(perms_model)
    @jwt_required()
    def post(self):
        """ 检查当前用户是否有指定权限 """
        try:
            # 确保请求是 JSON
            if not request.is_json:
                return {'message': 'Request must be JSON'}, 400

            current_user = get_jwt_identity()  # 获取当前用户的身份信息
            data = request.get_json(silent=True)  # 使用 silent=True 避免抛出异常

            if not data:
                return {'message': 'Invalid JSON data'}, 400

            required_permissions = data.get('permissions')  # 获取权限列表
            if not required_permissions:
                return {'message': 'At least one permission is required'}, 400

            # 获取当前用户的角色和权限
            user = Zbfwbuser.query.get(current_user)
            if user:
                user_roles = Zbfwbuserrole.query.filter_by(uid=user.t_zbfwb_user_id).all()
                roles = [role.rid for role in user_roles]

                # 获取角色权限
                role_permissions = Zbfwbroleperm.query.filter(Zbfwbroleperm.rid.in_(roles)).all()
                permissions = [perm.pid for perm in role_permissions]  # 获取用户的所有权限
                print(permissions)
                print(required_permissions)
                # 检查用户是否有指定权限（列表中的任意一个权限）
                if any(permission in permissions for permission in required_permissions):
                    return {'message': 'Permission granted'}, 200
                else:
                    return {'message': 'Permission denied'}, 403

            return {'message': 'User not found'}, 404

        except Exception as e:
            response_data = {
                "message": {
                    "result": 400,  # 查询异常
                    "result_text": f"查询异常: {str(e)}",
                    "count": 0,
                    "data": []
                }
            }
            return response_data, 400
